﻿using System;
using System.Collections.Generic;

using VSTalk.Engine.ViewModel.ContactList.ClientResources;
using VSTalk.Model;
using VSTalk.Tools;

namespace VSTalk.Engine.ViewModel.ContactList.Order
{
    public class DefaultResourceComparator : IResourceComparator
    {
        public IComparer<IClientResource> Comparator
        {
            get { return new DelegateComparer<IClientResource>(Compare); }
        }

        public int Compare(IClientResource x, IClientResource y)
        {
            if (x is InterlocutorResourceViewModel && y is RoomResourceViewModel)
            {
                return -1;
            }
            if (x is RoomResourceViewModel && y is InterlocutorResourceViewModel)
            {
                return 1;
            }
            if (x is InterlocutorResourceViewModel && y is InterlocutorResourceViewModel)
            {
                return CompareInterlocutors((InterlocutorResourceViewModel)x, (InterlocutorResourceViewModel)y);
            }
            if (x is RoomResourceViewModel && y is RoomResourceViewModel)
            {
                return CompareRooms((RoomResourceViewModel)x, (RoomResourceViewModel)y);
            }
            if (x is NullClientResource)
            {
                return 1;
            }
            if (y is NullClientResource)
            {
                return -1;
            }
            throw new NotImplementedException();
        }

        private int CompareInterlocutors(InterlocutorResourceViewModel x, InterlocutorResourceViewModel y)
        {
            var stateX = StateMeasure(x.Context.State);
            var stateY = StateMeasure(y.Context.State);
            if (stateX != stateY)
            {
                return (stateX > stateY) ? 1 : -1;
            }
            var showX = ShowMeasure(x.Context.Show);
            var showY = ShowMeasure(y.Context.Show);
            if (showX != showY)
            {
                return (showX > showY) ? 1 : -1;
            }
            return string.Compare(x.Interlocutor.Name, y.Interlocutor.Name, StringComparison.OrdinalIgnoreCase);
        }

        private int ShowMeasure(ShowType show)
        {
            switch (show)
            {
                case ShowType.NONE:
                case ShowType.chat:
                    return 1;
                case ShowType.away:
                case ShowType.xa:
                    return 2;
                case ShowType.dnd:
                    return 3;
                default:
                    return 0;
            }
        }

        private int StateMeasure(ContactState state)
        {
            switch (state)
            {
                case ContactState.Online:
                    return 1;
                case ContactState.Offline:
                    return 2;
                default:
                    return 0;
            }
        }

        private int CompareRooms(RoomResourceViewModel x, RoomResourceViewModel y)
        {
            return string.Compare(x.Room.Name, y.Room.Name, StringComparison.OrdinalIgnoreCase);
        }
    }
}